package com.dotflat.check.service.impl;

import com.alibaba.fastjson.JSON;
import com.dotflat.check.domain.Card;
import com.dotflat.check.domain.CheckCard;
import com.dotflat.check.domain.Checker;
import com.dotflat.check.po.*;
import com.dotflat.check.repository.CardInfoRepository;
import com.dotflat.check.repository.CardRepository;
import com.dotflat.check.repository.CheckCardRepository;
import com.dotflat.check.repository.CheckerRepository;
import com.dotflat.check.service.CheckerService;
import com.dotflat.rest.service.impl.AreableObjectBaseServiceImpl;
import com.matt.commons.dto.sso.StaffDTO;
import com.matt.commons.exception.BusinessException;
import com.matt.commons.page.PagerQuery;
import com.matt.domain.Children;
import com.matt.domain.ChildrenExtendInfo;
import com.matt.domain.ChildrenNurseryInfoRecord;
import com.matt.domain.mp.ParentUser;
import com.matt.domain.record.CheckRecord;
import com.matt.foundation.constant.ChildrenConstant;
import com.matt.foundation.model.ErrorCode;
import com.matt.foundation.utils.CopyUtils;
import com.matt.foundation.utils.DateUtil;
import com.matt.repository.AppUserRepository;
import com.matt.repository.ChildrenExtendInfoRepository;
import com.matt.repository.ChildrenRepository;
import com.matt.repository.base.BaseNativeSqlRepository;
import com.matt.repository.record.CheckRecordRepository;
import com.matt.repository.record.ChildrenNurseryInfoRecordRepository;
import com.matt.service.UploadService;
import com.matt.service.remoteCall.SsoCallService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;
import java.util.stream.Collectors;


@Service
public class CheckerServiceImpl extends AreableObjectBaseServiceImpl<Checker, CheckerRepository> implements CheckerService {

    @Autowired
    @Override
    public void setBaseRepository(CheckerRepository repository) {
        super.setBaseRepository(repository);
    }

    @Autowired
    private CheckerRepository checkerRepository;

    @Autowired
    private CheckCardRepository checkCardRepository;

    @Autowired
    private SsoCallService ssoCallService;

    @Autowired
    private BaseNativeSqlRepository baseNativeSqlRepository;

    @Autowired
    private CheckRecordRepository checkRecordRepository;

    @Autowired
    private ChildrenExtendInfoRepository childrenExtendInfoRepository;

    @Autowired
    private UploadService uploadService;

    @Autowired
    private AppUserRepository appUserRepository;

    @Autowired
    private CardRepository cardRepository;

    @Autowired
    private ChildrenNurseryInfoRecordRepository childrenNurseryInfoRecordRepository;

    @Autowired
    private ChildrenRepository childrenRepository;

    @Autowired
    private CardInfoRepository cardInfoRepository;

    @Override
    public Checker getId(String id) {
        return checkerRepository.getOne(id);
    }

    @Override
    public Checker getByDevSno(String devNo){
        return checkerRepository.findFirstByDevSnoAndDeletedIsFalse(devNo);
    }

    @Override
    public Checker addChecker(String areaId, String serialNO, String address) {
        Integer id = checkerRepository.getMaxId();
        if (Objects.isNull(id)) {
            id =  100000;
        } else {
            id = id+1;
        }
        Checker c = new Checker();
        if (Objects.nonNull(serialNO)) {
            c.setSerialNO(serialNO);
            c.setDevSno(serialNO);
        }
        if (Objects.nonNull(address)) {
            c.setAddress(address);
        }
        c.setCheckerId(id);
        c.setDirection(3);
        c.setAreaId(areaId);
        c.setManufacturer("TIANBO");
        c.setFeatures("opendoor|fullsync");
        c.setCreatedBy("");
        checkerRepository.save(c);
        return c;
    }

    @Override
    public Map login(Integer checkerId, Integer loginPass) {

        Checker checker = checkerRepository.findAllByCheckerIdAndLoginPass(checkerId, loginPass);
        if (Objects.isNull(checker)) {
            throw new BusinessException(ErrorCode.IS_TARGET, "对象不存在！");
        }
        Map map = ssoCallService.getStaffNameAndAreaName("", checker.getAreaId());
        Map map1 = JSON.parseObject(JSON.toJSONString(checker), Map.class);
        map1.put("areaName", map.get("areaName"));

        return map1;
    }

    @Override
    @Transactional
    public CheckCard addCard(String areaId, String cardNo, String userId, Integer type, String relationUserId) {

        Card card1 = cardRepository.findByCardNo(cardNo);
        if (null ==card1) {
            throw new BusinessException(ErrorCode.IS_TARGET, "卡号未导入！");
        }
        CheckCard checkCard = checkCardRepository.findByCardNo(cardNo);
        if (null !=checkCard){
            throw new BusinessException(ErrorCode.UNDEFINED, "卡号已绑定！");
        }
        card1.setStatus(1);
        card1.setPurposeType("考勤机");
        card1.setType(2);
        cardRepository.save(card1);


        CheckCard card = new CheckCard();
        card.setCardNo(cardNo);
        card.setAreaId(areaId);
        card.setCardCode(card1.getCardCode());
        card.setUserId(userId);
        card.setCreatedBy("");
        card.setType(type);
        card.setStatus(1);
        if (Objects.nonNull(relationUserId)) {
            card.setRelationUserId(relationUserId);
        }
        checkCardRepository.save(card);
        return card;
    }

    @Override
    public List<CheckUserPO> getUser(String areaId, Integer type, Integer whole) {
        List<CheckUserPO> list = new ArrayList<>();
        if (type == 1 || type == 0) {
            List<CheckUserPO> checkUserPOList =  cardInfoRepository.getCheckUserByChildren(areaId,type,whole);
            list.addAll(checkUserPOList);
        }
        if (type == 2 || type == 0) {
            List<StaffDTO> list1 = ssoCallService.getStaffDTOList(areaId);
            List<String> ids = list1.stream().map(k -> k.getId()).collect(Collectors.toList());
            String sql = " SELECT * FROM  c_check_card WHERE userId in (:1) AND type =  2";
            List params = new ArrayList();
            params.add(ids);
            List<CheckCard> objectArrayList = baseNativeSqlRepository.sqlObjectList(sql, params, CheckCard.class);
            for (int j = 0; j < list1.size(); j++) {
                CheckUserPO checkUser = new CheckUserPO();
                checkUser.setKgId(areaId);
                checkUser.setHeadImage(list1.get(j).getHeadImgUrl());
                checkUser.setUserName(list1.get(j).getRealName());
                checkUser.setUserId(list1.get(j).getId());
                checkUser.setSex(list1.get(j).getGender());
                for (int i = 0; i < objectArrayList.size(); i++) {
                    if (StringUtils.equals(list1.get(j).getId(), objectArrayList.get(i).getUserId())) {
                        checkUser.setSACardNo(objectArrayList.get(i).getCardNo());
                        checkUser.setState(objectArrayList.get(i).getStatus());
                        if (whole == 1) {
                            list.add(checkUser);
                        }
                    }
                }
                if (whole != 1) {
                    list.add(checkUser);
                }
            }
        }

        if (type == 3 || type == 0) {
            List<CheckUserPO> userPOList = cardInfoRepository.getCheckUserPO(areaId,type,whole);
            list.addAll(userPOList);
        }
        return list;
    }


    @Override
    public List<CardPO> getCard(String areaId, Integer type, Integer whole) {
        List<CardPO> list = new ArrayList<>();
        if (type == 1 || type == 0) {
            List<CardPO>  cardPOList = cardInfoRepository.getAreaIdByChildrenCardList( areaId,  type,  whole);
            list.addAll(cardPOList);
        }
        if (type == 2 || type == 0) {
            List<StaffDTO> list1 = ssoCallService.getStaffDTOList(areaId);
            List<String> ids = list1.stream().map(k -> k.getId()).collect(Collectors.toList());

            String sql = " SELECT * FROM  c_check_card WHERE userId in (:1) AND type =  2";

            List params = new ArrayList();
            params.add(ids);
            List<CheckCard> objectArrayList = baseNativeSqlRepository.sqlObjectList(sql, params, CheckCard.class);

            for (int j = 0; j < list1.size(); j++) {
                CardPO card = new CardPO();
                card.setKgId(areaId);
                card.setUserId(list1.get(j).getId());
                card.setCardType(2);
                for (int i = 0; i < objectArrayList.size(); i++) {
                    if (StringUtils.equals(list1.get(j).getId(), objectArrayList.get(i).getUserId())) {
                        card.setCardNo(objectArrayList.get(i).getCardCode());
                        card.setCreateTime(DateUtil.formatDateToStr(objectArrayList.get(i).getCreated()));
                        card.setId(objectArrayList.get(i).getId());
                        card.setState(objectArrayList.get(i).getStatus());
                        if (whole == 1) {
                            list.add(card);
                            continue;
                        }
                    }
                }
                if (whole != 1) {
                    list.add(card);
                }
            }
        }
        if (type == 3 || type == 0) {
            List<CardPO>  cardPOList = cardInfoRepository.getAreaIdByUserCardList( areaId,  type,  whole);
            list.addAll(cardPOList);
        }
        return list;
    }

    @Override
    public void delete(String cardNo) {
        checkCardRepository.deleteCardNo(cardNo);
    }


    @Override
    public CheckRecord addRecord(String cardNo, int status, String time, String checkerId, MultipartFile file) {

        Checker checker = checkerRepository.getOne(checkerId);
        if (Objects.isNull(checker)) {
            throw new BusinessException(ErrorCode.IS_TARGET, "考勤机ID不存在！");
        }
        CheckCard card = checkCardRepository.findByCardCode(cardNo);
        if (Objects.isNull(card)) {
            throw new BusinessException(ErrorCode.IS_TARGET, "卡内码不存在！");
        }
        Date now = new Date();
        String currentDay = DateUtil.millisToDateTime(now.getTime(), "yyyy-MM-dd");
        Map<String, Date> map = DateUtil.getCurrentDayBeginAndEnd(currentDay);
        Date begin = map.get("beg");
        Date end = map.get("end");
        String childrenId = card.getUserId();
        //类型等于家长的时候
        if (card.getType() == 3) {
            childrenId = card.getRelationUserId();
        }

        Children children = childrenRepository.getOne(childrenId);
        //查询是否有记录
        CheckRecord record = checkRecordRepository.findFirstByCheckInTimeBetweenAndChildrenIdAndCheckOutTimeIsNull(begin, end, childrenId);

        if (Objects.isNull(record)) {
            record = new CheckRecord();
        }
        record.setChildrenId(childrenId);
        String image = "";
        if (Objects.nonNull(file)) {
            image = uploadService.uploadCheckInRecordImg(childrenId, file);
        }
        if (status == 1) {
            record.setCheckInMediaUrl(image);
            record.setCheckInTime(DateUtil.parseToDateMilis(time));
            if (card.getType() == 3) {
                ParentUser user = appUserRepository.getById(card.getUserId());
                if (Objects.isNull(user)) {
                    throw new BusinessException(ErrorCode.IS_TARGET, "对象不存在！");
                }
                record.setRelateId(card.getUserId());
                record.setRelateName(user.getName());
                record.setRelateHeadImage(image);
            }
        }
        if (status == 2) {
            record.setCheckOutMediaUrl(image);
            record.setCheckOutTime(DateUtil.parseToDateMilis(time));
            if (card.getType() == 3) {
                ParentUser user = appUserRepository.getById(card.getUserId());
                if (Objects.isNull(user)) {
                    throw new BusinessException(ErrorCode.IS_TARGET, "对象不存在！");
                }
                record.setRelateId(card.getUserId());
                record.setRelateName(user.getName());
                record.setRelateHeadImage(image);
            }
        }
        record.setCheckerId(checker.getId());
        record.setCheckerAddress(checker.getAddress());
        record.setCardNo(cardNo);
        record.setStatus(status);
        record.setUserType(card.getType());

        checkRecordRepository.save(record);
        int day = DateUtil.birthdayDay(end, begin) + 1;
        List<ChildrenNurseryInfoRecord> list = childrenNurseryInfoRecordRepository.findAllByAndChildrenIdTime(children.getId(), end, begin);
        //非
        if (list.size() == 0 && (card.getType() != 2 && null != childrenId)) {

            ChildrenExtendInfo childrenExtendInfo = childrenExtendInfoRepository.findByChildrenId(childrenId);
            if (Objects.nonNull(childrenExtendInfo)) {
                childrenExtendInfo.setCheckStatus(status);
                childrenExtendInfo.setCheckTime(DateUtil.parseToDateHour(time));
                childrenExtendInfoRepository.save(childrenExtendInfo);
            }
            //添加考勤流水记录
            ChildrenNurseryInfoRecord childrenNurseryInfoRecord = new ChildrenNurseryInfoRecord();

            childrenNurseryInfoRecord.setChildrenId(children.getId());
            childrenNurseryInfoRecord.setCreatedName(children.getName());
            childrenNurseryInfoRecord.setStatus(status);
            childrenNurseryInfoRecord.setHealthyStatus(0);
            childrenNurseryInfoRecord.setBeginDate(DateUtil.parseToDateHour(time));
            childrenNurseryInfoRecord.setEndDate(DateUtil.parseToDateHour(time));
            childrenNurseryInfoRecord.setEffectDay(day);
            childrenNurseryInfoRecord.setType(0);
            childrenNurseryInfoRecord.setNurseryOriginalEndDate(childrenExtendInfo.getNurseryEndDate());
            childrenNurseryInfoRecord.setNurseryEndDate(childrenExtendInfo.getNurseryEndDate());
            childrenNurseryInfoRecord.setSurplusOriginalLeaveDay(childrenExtendInfo.getSurplusLeaveDay());
            childrenNurseryInfoRecord.setSurplusLeaveDay(childrenExtendInfo.getSurplusLeaveDay());
            childrenNurseryInfoRecordRepository.save(childrenNurseryInfoRecord);
        }

        return record;
    }


    @Override
    public Page<UserCardPO> getAllList(String areaId, Integer status, String classId, PagerQuery page) {
        if (null == status) {
            status = 0;
        }

        List<UserCardInfoPO> list = cardInfoRepository.getUserCardInfoPO(areaId, status, classId, page);
        List<UserCardPO> ret = list.stream().map(o -> {
            UserCardPO po = new UserCardPO();
            CopyUtils.copyProperties(o, po);
            po.setStatusVal(ChildrenConstant.CheckStatus.JOIN.get(o.getStatus()).valueOf());
            return po;
        }).collect(Collectors.toList());
        Integer listCount = cardInfoRepository.getUserCardInfoCount(areaId, status, classId);
        return new PageImpl<UserCardPO>(ret, PageRequest.of(page.getPageNum(), page.getPageSize()), listCount);
    }

    @Override
    public Page<UserRelationCardInfoPO> getUserCardList(String areaId, Integer status, String classId, PagerQuery page) {
        if (null == status) {
            status = 0;
        }

        List<UserRelationCardInfoPO> list = cardInfoRepository.getUserRelationCardInfoPO(areaId, status, classId, page);
        List<UserRelationCardInfoPO> ret = list.stream().map(o -> {
            UserRelationCardInfoPO po = new UserRelationCardInfoPO();
            CopyUtils.copyProperties(o, po);
            po.setStatusVal(ChildrenConstant.CheckStatus.JOIN.get(o.getStatus()).valueOf());
            return po;
        }).collect(Collectors.toList());
        Integer listCount = cardInfoRepository.getUserRelationCardInfoPOCount(areaId, status, classId);
        return new PageImpl<UserRelationCardInfoPO>(ret, PageRequest.of(page.getPageNum(), page.getPageSize()), listCount);
    }

    @Override
    public Page<CheckCard> findAllByAreaId(String areaId, PagerQuery page) {
        Pageable pageable = PageRequest.of(page.getPageNum(), page.getPageSize());
        return checkCardRepository.findByAreaId(areaId, pageable);
    }

    @Override
    public List<CheckCard> findAllByUserIdsAndType(List<String> userIds, int type) {
        return checkCardRepository.findByTypeAndUserIdIn(type, userIds.toArray(new String[userIds.size()]));
    }

    @Override
    public CardInfoPO getCardStatus(String areaId, String cardNo,String ticket) {
        Card card1 = cardRepository.findByCardNo(cardNo);
        if (null ==card1) {
            throw new BusinessException(ErrorCode.IS_TARGET, "卡号未导入！");
        }
        CheckCard card = checkCardRepository.findByCardNo(cardNo);
        if (null == card) {
            return null;
        }
        CardInfoPO cardInfoPO = null;
        if (card.getType() == 1) {
            UserRelationCardInfoPO userRelationCardInfoPO = cardInfoRepository.getUserRelationCardInfo_v2(areaId, card.getUserId(), null, cardNo);
            if (null != userRelationCardInfoPO) {
                cardInfoPO = new CardInfoPO();
                cardInfoPO.setCardInfo("【幼儿卡】");
                cardInfoPO.setClassInfo( userRelationCardInfoPO.getClassName());
                cardInfoPO.setStatusVal( ChildrenConstant.CheckStatus.JOIN.get(userRelationCardInfoPO.getStatus()).valueOf());
                cardInfoPO.setUserInfo( userRelationCardInfoPO.getChildrenName());
            }
        }

        if (card.getType() == 3) {
            UserRelationCardInfoPO userRelationCardInfoPO = cardInfoRepository.getUserRelationCardInfo_v2(areaId, null, card.getUserId(), cardNo);
            if (null != userRelationCardInfoPO) {
                cardInfoPO = new CardInfoPO();
                cardInfoPO.setCardInfo("【家长卡】");
                cardInfoPO.setUserInfo( userRelationCardInfoPO.getChildrenName());
                cardInfoPO.setClassInfo( userRelationCardInfoPO.getClassName());
                cardInfoPO.setStatusVal( ChildrenConstant.CheckStatus.JOIN.get(userRelationCardInfoPO.getStatus()).valueOf());
                cardInfoPO.setUserInfo( userRelationCardInfoPO.getChildrenName());
            }
        }
        if (card.getType() == 2) {
            StaffDTO staffDTO = ssoCallService.getStaffDTO(ticket,card.getUserId());
            cardInfoPO = new CardInfoPO();
            cardInfoPO.setCardInfo("【教师卡】");
            cardInfoPO.setUserInfo( staffDTO.getRealName());
        }
        if (null ==cardInfoPO){
            cardInfoPO = new CardInfoPO();
            cardInfoPO.setCardInfo("【未发卡】");
        }
        return cardInfoPO;
    }

    @Override
    public List<CheckCard> findByTypeAndAreaId(int type, String areaId) {
        return checkCardRepository.findByTypeAndAreaId(type,areaId);
    }

    @Override
    public Checker getByDevSno1(String devSno, String areaId) {
        return checkerRepository.findFirstByDevSnoAndAreaIdAndDeletedIsFalse(devSno,areaId);
    }
}
